/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package comm

import (
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/common/verifier"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/providers/core"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/providers/ichain"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/thirdparty/ichain/security/utils"
	"github.com/tjfoc/gmsm/gmtls"
	"github.com/tjfoc/gmsm/gmtls/gmcredentials"
	x509GM "github.com/tjfoc/gmsm/x509"
	"google.golang.org/grpc/credentials"
)

// TLSConfig 生成tls配置，对于非国密Support字段为nil
// @param cert
// @param serverName
// @param config
// @return *gmtls.Config
// @return error
func TLSConfig(cert *x509GM.Certificate, serverName string, config ichain.EndpointConfig) (*gmtls.Config, error) {

	if cert != nil {
		config.TLSCACertPool().Add(cert)
	}

	isGM := utils.IsSM2SignedCert(cert)

	certPool, err := config.TLSCACertPool().Get()
	if err != nil {
		return nil, err
	}
	var support *gmtls.GMSupport
	if isGM {
		support = gmtls.NewGMSupport()
	}
	return &gmtls.Config{
		GMSupport:    support,
		RootCAs:      certPool,
		Certificates: config.TLSClientCerts(),
		ServerName:   serverName,
	}, nil
}

// TLSCertHash 计算tls证书hash
// @param csp
// @param config
// @return []byte
// @return error
func TLSCertHash(csp core.CryptoSuite, config ichain.EndpointConfig) ([]byte, error) {
	certs := config.TLSClientCerts()

	if len(certs) == 0 {
		return csp.Hash([]byte(""))
	}

	cert := certs[0]
	if len(cert.Certificate) == 0 {
		return csp.Hash([]byte(""))
	}

	return csp.Hash(cert.Certificate[0])
}

// ParseCertToTransportCredential 解析证书返回grpc凭证
func ParseCertToTransportCredential(certificate *x509GM.Certificate, serverName string, config ichain.EndpointConfig) (credentials.TransportCredentials, error) {
	tlsConfig, err := TLSConfig(certificate, serverName, config)
	if err != nil {
		return nil, err
	}
	tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509GM.Certificate) error {
		return verifier.VerifyInodeCertificate(rawCerts, verifiedChains)
	}
	return gmcredentials.NewTLS(tlsConfig), nil
}
